﻿using DocumentFormat.OpenXml.Lite.Helper;
using DocumentFormat.OpenXml.Lite.Interfaces;
using DocumentFormat.OpenXml.Lite.Shared;
using DocumentFormat.OpenXml.Lite.WordprocessingML.Word.Types;
using DocumentFormat.OpenXml.Lite.Xml;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;

namespace DocumentFormat.OpenXml.Lite.WordprocessingML.Word.Table.Properties
{
    [XmlRoot("tblBorders", Namespace = Constants.WordMain)]
    public class Borders : ITablePropElement
    {
        [XmlElement("top", Namespace = Constants.WordMain)]
        public BorderDefinition Top { get; set; }

        [XmlElement("bottom", Namespace = Constants.WordMain)]
        public BorderDefinition Bottom { get; set; }

        [XmlElement("left", Namespace = Constants.WordMain)]
        public BorderDefinition Left { get; set; }

        [XmlElement("right", Namespace = Constants.WordMain)]
        public BorderDefinition Right { get; set; }

        /// <summary>
        /// Table Inside Horizontal Edges Border
        /// </summary>
        [XmlElement("insideH", Namespace = Constants.WordMain)]
        public BorderDefinition InsideHorizontalEdges { get; set; }

        /// <summary>
        /// Table Inside Vertical Edges Border
        /// </summary>
        [XmlElement("insideV", Namespace = Constants.WordMain)]
        public BorderDefinition InsideVerticalEdges { get; set; }

        public Borders() { }

        public void Copy(object obj)
        {
            if (obj is Borders)
            {
                this.Top = (obj as Borders).Top;
                this.Bottom = (obj as Borders).Bottom;
                this.Left = (obj as Borders).Left;
                this.Right = (obj as Borders).Right;
                this.InsideVerticalEdges = (obj as Borders).InsideVerticalEdges;
                this.InsideHorizontalEdges = (obj as Borders).InsideHorizontalEdges;
            }
        }
    }

    #region BorderDefinition

    public class BorderDefinition : XmlSerializable, ICopyable
    {
        [XmlAttribute("val", Namespace = Constants.WordMain, Form = XmlSchemaForm.Qualified)]
        public ST_Border Value { get; set; }

        /// <summary>
        /// Hexadecimal number. Length: 6 or 'auto'
        /// </summary>
        [Optional]
        [XmlAttribute("color", Namespace = Constants.WordMain, Form = XmlSchemaForm.Qualified)]
        public string Color
        {
            get { return color; }
            set
            {
                if (value == null || (value.Length != 6 && value != "auto") ||
                    (value.Length == 6 && !Helpers.ParseHexadecimalValue(value)))
                {
                    throw new ArgumentException("String: " + value +
                        "is not a valid hexadecimal string or length is not 6!");
                }

                color = value;
            }
        }

        [Optional]
        [XmlAttribute("themeColor", Namespace = Constants.WordMain, Form = XmlSchemaForm.Qualified)]
        public Nullable<ST_ThemeColor> ThemeColor { get; set; }

        /// <summary>
        /// Hexadecimal number. Length: 2
        /// </summary>
        [Optional]
        [XmlAttribute("themeTint", Namespace = Constants.WordMain, Form = XmlSchemaForm.Qualified)]
        public string ThemeColorTint
        {
            get { return themeColorTint; }
            set
            {
                if (value == null || value.Length != 2 || !Helpers.ParseHexadecimalValue(value))
                {
                    throw new ArgumentException("String: " + value +
                        "is not a valid hexadecimal string or length is not 2!");
                }

                themeColorTint = value;
            }
        }

        /// <summary>
        /// Hexadecimal number. Length: 2
        /// </summary>
        [Optional]
        [XmlAttribute("themeShade", Namespace = Constants.WordMain, Form = XmlSchemaForm.Qualified)]
        public string ThemeColorShade
        {
            get { return themeColorShade; }
            set
            {
                if (value == null || value.Length != 2 || !Helpers.ParseHexadecimalValue(value))
                {
                    throw new ArgumentException("String: " + value +
                        "is not a valid hexadecimal string or length is not 2!");
                }

                themeColorShade = value;
            }
        }

        [Optional]
        [XmlAttribute("sz", Namespace = Constants.WordMain, Form = XmlSchemaForm.Qualified)]
        public Nullable<uint> Width { get; set; }

        [Optional]
        [XmlAttribute("space", Namespace = Constants.WordMain, Form = XmlSchemaForm.Qualified)]
        public Nullable<uint> Space { get; set; }

        [Optional]
        [XmlAttribute("shadow", Namespace = Constants.WordMain, Form = XmlSchemaForm.Qualified)]
        public Nullable<ST_OnOff> Shadow { get; set; }

        [Optional]
        [XmlAttribute("frame", Namespace = Constants.WordMain, Form = XmlSchemaForm.Qualified)]
        public Nullable<ST_OnOff> Frame { get; set; }

        [XmlIgnore]
        private string color;

        [XmlIgnore]
        private string themeColorTint;

        [XmlIgnore]
        private string themeColorShade;

        public BorderDefinition() { }

        public void Copy(object obj)
        {
            if (obj is BorderDefinition)
            {
                this.Value = (obj as BorderDefinition).Value;

                this.Color = (obj as BorderDefinition).Color;
                this.ThemeColor = (obj as BorderDefinition).ThemeColor;
                this.ThemeColorTint = (obj as BorderDefinition).ThemeColorTint;
                this.ThemeColorShade = (obj as BorderDefinition).ThemeColorShade;

                this.Width = (obj as BorderDefinition).Width;
                this.Space = (obj as BorderDefinition).Space;
                this.Shadow = (obj as BorderDefinition).Shadow;
                this.Frame = (obj as BorderDefinition).Frame;
            }
        }
    }

    #endregion
}
